package com.hxht.storage.server.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hxht.storage.server.bean.CurrentRecordingBean;
import com.hxht.storage.server.bean.RecordMarkBean;
import com.hxht.storage.server.bean.RecordSearchBean;
import com.hxht.storage.server.bean.RecordSearchResultBean;
import com.hxht.storage.server.dao.RecordMarkDao;
import com.hxht.storage.server.pojo.BaseRecordInfo;
import com.hxht.storage.server.pojo.PlanRecordInfo;
import com.hxht.storage.server.pojo.RecordMarkInfo;
import com.hxht.storage.server.pojo.VideoManualRecord;
import com.hxht.storage.server.service.ManualRecordService;
import com.hxht.storage.server.service.PlanRecordService;
import com.hxht.storage.server.service.RecordSearchService;
import com.hxht.storage.server.util.NvrBeanTransUtil;

@Service
public class RecordSearchServiceImpl implements RecordSearchService {
	
	private static final Logger LOG = Logger.getLogger(RecordSearchServiceImpl.class);

	@Autowired
	private ManualRecordService manualRecordService;
	
	@Autowired
	private PlanRecordService planRecordService;
	
	@Autowired
	private RecordMarkDao recordMarkDao;
	
	@Override
	public List<RecordSearchResultBean> searchRecordByDevice(
			RecordSearchBean searchBean) {
		
		LOG.info("search record is beginning---------------");
//		LOG.info("---deviceId 	  : " + searchBean.getVideoDeviceId() + "---");
//		LOG.info("---channelIndex : " + searchBean.getVideoDeviceChannelIndex() + "---");
		LOG.info("---search type  : " + Integer.toHexString(searchBean.getType()));
		
		List<RecordSearchResultBean> resultBeanList = new ArrayList<RecordSearchResultBean>();
		
		
		if (isNeedSearchManualRecord(searchBean)){
			// 搜索手工录像的历史记录信息
			// 手工录像搜索，直接搜索的存储服务器数据库，没有去nvr 中 实时搜索
			List<RecordSearchResultBean> manualResult = manualRecordService.searchRecordByDevice(searchBean,
					getManualRecordSearchTypeListFromSearchBean(searchBean));
			if (manualResult !=null && manualResult.size() != 0){
				resultBeanList.addAll(manualResult);
			}
		}
		
		if (isNeedSearchPlanRecord(searchBean)){
			// 搜索计划录像的历史记录信息
			// 计划录像的 搜索返回结果都是从NVR中JNI调用查询接口返回的
			List<RecordSearchResultBean> planResult = planRecordService.searchRecordByDevice(searchBean,
					getPlanRecordSearchTypeListFromSearchBean(searchBean));
			if (planResult != null && planResult.size() != 0){
				resultBeanList.addAll(planResult);
			}
		}
		
		LOG.info("search record is end---------------");
		return resultBeanList;
	}

	/**
	 *byte位：  5      4      3      2      1  
	 *      手动录像   命令触发位 报警触发位  移动侦测位    定时位 
	 * 0xff 代表全部
	 *
	 * @param searchBean
	 * @return
	 */
	private boolean isNeedSearchPlanRecord(RecordSearchBean searchBean) {
		
		int type = searchBean.getType();

		// 0xff 代表 搜索全部
		if (type == 0xff)
			return true;
		
		// 计划录像位 已置
		if ( (type & TYPE_PLAN_RECORD) != 0 ) 
			return true;
		
		// 报警触发位 已置
		if ( (type & TYPE_ALARM) != 0 ) 
			return true;
		
		// 移动侦测位 已置
		if ( (type & TYPE_MOTION_DETECT) != 0 ) 
			return true;
		
		return false;
	}
	
	public boolean isPlanRecordType(RecordSearchBean searchBean){
		int type = searchBean.getType();

		// 0xff 代表 搜索全部
		if (type == 0xff)
			return true;
		
		// 计划录像位 已置
		if ( (type & TYPE_PLAN_RECORD) != 0 ) 
			return true;
		
		return false;
	}
	
	/**
	 * 将 用户请求搜索的Type，转化为 计划录像 nvr查询中使用的type
	 * @param searchBean
	 * @return
	 */
	private List<Integer> getPlanRecordSearchTypeListFromSearchBean(
			RecordSearchBean searchBean) {
		
		List<Integer> typeList = new ArrayList<Integer>();
		
		// 如果 用户类型指定是0xff，表示 全部类型搜索
		if (searchBean.getType() == 0xff){
			typeList.add(NVR_PLAN_TYPE_ALL);
			return typeList;
		}
		
		// 定时录像类型
		if (isPlanRecordType(searchBean)){
			typeList.add(NVR_PLAN_TYPE_PLAN_RECORD);
		}
		
		// 报警触发类型
		if (isAlarmType(searchBean)){
			typeList.add(NVR_PLAN_TYPE_ALARM);
		}
		
		// 移动侦测类型
		if (isMotionDetectType(searchBean)){
			typeList.add(NVR_PLAN_TYPE_MOTION_DETECT);
		}
		
		if (isManualType(searchBean)){
			
		}
		
		return typeList;
	}
	
	/**
	 * 将 用户请求搜索的Type，转化为 计划录像 nvr查询中使用的type
	 * @param searchBean
	 * @return
	 */
	private List<Integer> getManualRecordSearchTypeListFromSearchBean(
			RecordSearchBean searchBean) {
		
		List<Integer> typeList = new ArrayList<Integer>();
		
		// 如果 用户类型指定是0xff，表示 全部类型搜索
		if (searchBean.getType() == 0xff){
			typeList.add(NVR_MANUAL_TYPE_MANUAL);
			typeList.add(NVR_MANUAL_TYPE_COMMAND);
			return typeList;
		}
		
		// 手工录像类型
		if (isManualType(searchBean)){
			typeList.add(NVR_MANUAL_TYPE_MANUAL);
		}
		
		// 命令录像类型
		if (isCommandTriggerType(searchBean)){
			typeList.add(NVR_MANUAL_TYPE_COMMAND);
		}
		
		return typeList;
	}
	
	private boolean isCommandTriggerType(RecordSearchBean searchBean) {
		int type = searchBean.getType();

		// 0xff 代表 搜索全部
		if (type == 0xff)
			return true;
		
		// 命令触发位 已置
		if ( (type & TYPE_COMMAND_TRIGGER) != 0 ) 
			return true;
		
		return false;
	}

	private boolean isManualType(RecordSearchBean searchBean) {
		int type = searchBean.getType();

		// 0xff 代表 搜索全部
		if (type == 0xff)
			return true;
		
		// 命令触发位 已置
		if ( (type & TYPE_MANUAL_RECORD) != 0 ) 
			return true;
		
		return false;
	}

	public boolean isAlarmType(RecordSearchBean searchBean){
		int type = searchBean.getType();

		// 0xff 代表 搜索全部
		if (type == 0xff)
			return true;
		
		// 报警触发位 已置
		if ( (type & TYPE_ALARM) != 0 ) 
			return true;
		
		return false;
	}
	
	public boolean isMotionDetectType(RecordSearchBean searchBean){
		int type = searchBean.getType();

		// 0xff 代表 搜索全部
		if (type == 0xff)
			return true;
		
		// 移动侦测位 已置
		if ( (type & TYPE_MOTION_DETECT) != 0 ) 
			return true;
		
		return false;
	}

	/**
	 *byte位：  5      4      3      2      1  <br/>
	 *      手动录像   命令触发位 报警触发位  移动侦测位    定时位  <br/>
	 * 0xff 代表全部
	 *
	 * @param searchBean
	 * @return
	 */
	private boolean isNeedSearchManualRecord(RecordSearchBean searchBean) {
		
		int type = searchBean.getType();

		// 0xff 代表 搜索全部
		if (type == 0xff)
			return true;
		
		// 命令触发位 已置
		if ( (type & TYPE_COMMAND_TRIGGER) != 0 ) 
			return true;
		
		// 手工录像位 已置
		if ( (type & TYPE_MANUAL_RECORD) != 0 ) 
			return true;
		
		return false;
	}

	@Override
	public List<RecordSearchResultBean> searchManualRecordByMark(String mark) {
		
		LOG.info("search duty check record is beginning---------------");
		LOG.info("---duty check id  : " + mark);
		
		if (StringUtils.isEmpty(mark)){
			LOG.warn("mark is null");
			return null;
		}
		
		List<RecordSearchResultBean> resultList= manualRecordService.searchRecordByMark(mark);
		
		return resultList;
	}
	
	@Override
	@Transactional(value = "nvmpJpaEM", propagation = Propagation.REQUIRED)
	public boolean addRecordMark(RecordMarkBean recordMarkBean) {
		
		Date markTime = NvrBeanTransUtil.transStringToDate(recordMarkBean.getMarkTime());
		
		// 标注时间解析出错，返回false
		if (markTime == null){
			LOG.warn("record mark time is error! + markTime = " + recordMarkBean.getMarkTime());
			return false;
		}
		
		String recordUuid = recordMarkBean.getRecordUuid();
		if (recordUuid == null){
			LOG.warn("record uuid is null!");
			return false;
		}
		
		BaseRecordInfo markRecord = manualRecordService.getRecordByUuid(recordUuid);

		if (markRecord == null){
			markRecord = planRecordService.getrecordByUuid(recordUuid);
		}
		
		if (markRecord == null){
			LOG.warn("can't find record whose uuid = " + recordUuid);
			LOG.warn("markTime is " + recordMarkBean.getMarkTime());
			return false;
		}
		// 生成 record mark,并插入数据库
		RecordMarkInfo mark = new RecordMarkInfo();
		mark.setUuid(recordMarkBean.getUuid());
		mark.setRecord(markRecord);
		mark.setMarkName(recordMarkBean.getMarkName());
		mark.setMarkTime(markTime);
		mark.setMarkContent(recordMarkBean.getMarkContent());
		recordMarkDao.insert(mark);
		
		LOG.info("add record mark! mark = " + mark.getMarkName());
		
		return true;
	}
	
	@Override
	@Transactional(value = "nvmpJpaEM", propagation = Propagation.REQUIRED)
	public void delRecordMark(String uuid){
		
		LOG.info("delete record mark! uuid = " + uuid);
		
		if (StringUtils.isEmpty(uuid))
			return;
		
		recordMarkDao.removeByUuid(uuid);
	}

	@Override
	public List<CurrentRecordingBean> getCurrentRecording() {

		LOG.info("user request to get current recording info!");
		
		List<CurrentRecordingBean> recordingList = new ArrayList<CurrentRecordingBean>();
		
		// 获得正在录像的 手工录像信息
		List<VideoManualRecord> manualRecordingList = manualRecordService.getRecordingDevice();
		
		for (VideoManualRecord recording:manualRecordingList){
			CurrentRecordingBean recordingBean = NvrBeanTransUtil.transManualRecordingToRecordingBean(recording);
			recordingList.add(recordingBean);
		}
		
		// 获得正在录像的 计划录像信息
		List<PlanRecordInfo> planRecordingList = planRecordService.getRecordingDevice();
		
		for (PlanRecordInfo recording:planRecordingList){
			CurrentRecordingBean recordingBean = NvrBeanTransUtil.transPlanRecordingToRecordingBean(recording);
			recordingList.add(recordingBean);
		}
		
		LOG.info("get current recording info success!");
		
		return recordingList;
	}

	@Override
	@Transactional(value = "nvmpJpaEM", propagation = Propagation.REQUIRED)
	public Boolean updateRecordMark(String uuid, String content) {
		
		RecordMarkInfo markInfo = recordMarkDao.getByUuid(uuid);
		
		if (markInfo == null){
			LOG.warn("can't find the record mark by uuid = " + uuid);
			return false;
		}
		markInfo.setMarkContent(content);
		
		LOG.info("update the record mark's content success！uuid = " + uuid);
		return true;
	}
	
}
